package org.example.service.currency.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.example.controller.req.CurrencyHistoryReq;
import org.example.dao.currency.CurrencyExchangeRateDao;
import org.example.dao.currency.CurrencyMsgDao;
import org.example.entity.currency.CurrencyExchangeRateEntity;
import org.example.entity.currency.CurrencyMsgEntity;
import org.example.service.currency.CurrencyExchangeRateService;
import org.example.service.currency.CurrencyService;
import org.example.service.utils.Constant;
import org.example.service.utils.okhttp.OkHttpClients;
import org.example.service.utils.okhttp.OkHttpParam;
import org.example.service.utils.okhttp.OkhttpResult;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class CurrencyServiceImpl extends ServiceImpl<CurrencyMsgDao, CurrencyMsgEntity> implements CurrencyService {

    @Value("${currency.appKey}")
    private String appKey;
    @Resource
    private CurrencyExchangeRateDao currencyExchangeRateDao;

    @Resource
    private CurrencyExchangeRateService currencyExchangeRateService;

    /**
     * 同步货币信息
     *
     * @param apiRes
     */
    @Override
    public void syncCurrency(String apiRes) {
        log.info("同步信息:{}", apiRes);
        JSONObject jsonObject = JSONObject.parseObject(apiRes);
        Object timeLastUpdated = jsonObject.get("time_last_updated");
        Object rates = jsonObject.get("rates");
        HashMap<String, Object> hashMap = JSONObject.parseObject(JSONObject.toJSONString(rates), HashMap.class);
        System.out.printf(timeLastUpdated + "");
        List<CurrencyMsgEntity> list = new ArrayList<>();
        hashMap.forEach((key, val) -> {
            log.info("key:{}->value:{}", key, val);
            CurrencyMsgEntity currencyMsgEntity = new CurrencyMsgEntity();
            currencyMsgEntity.setCurrencyEn(key);
            list.add(currencyMsgEntity);
        });
        this.saveBatch(list);
    }

    /**
     * 同步货币信息汇率
     *
     * @param apiRes
     */
    @Override
    public void syncCurrencyRate(String apiRes) {
        log.info("同步信息:{}", apiRes);
        JSONObject jsonObject = JSONObject.parseObject(apiRes);
        Object rates = jsonObject.get("rates");
        Object base = jsonObject.get("base");
        HashMap<String, Object> hashMap = JSONObject.parseObject(JSONObject.toJSONString(rates), HashMap.class);
        List<CurrencyExchangeRateEntity> list = new ArrayList<>();
        hashMap.forEach((key, val) -> {
            log.info("key:{}->value:{}", key, val);
            CurrencyExchangeRateEntity currencyExchangeRateEntities = currencyExchangeRateDao.selectOne(
                    new QueryWrapper<CurrencyExchangeRateEntity>().eq("currency_master_en", base).eq("currency_slave_en", key)
            );
            if (!ObjectUtil.isEmpty(currencyExchangeRateEntities)) {
                // 更新
                currencyExchangeRateEntities.setSlaveExchangeRate(getBigDecimal(val));
                currencyExchangeRateEntities.setMasterExchangeRate(getBigDecimal(val));
                list.add(currencyExchangeRateEntities);
            } else {
                //创建
                CurrencyExchangeRateEntity currencyExchangeRate = new CurrencyExchangeRateEntity();
                currencyExchangeRate.setCurrencyMasterEn((String) base);
                currencyExchangeRate.setCurrencySlaveEn(key);
                currencyExchangeRate.setMasterExchangeRate(getBigDecimal(val));
                currencyExchangeRate.setSlaveExchangeRate(getBigDecimal(val));
                currencyExchangeRateDao.insert(currencyExchangeRate);
            }
        });
        if (CollectionUtil.isNotEmpty(list)){
            currencyExchangeRateService.updateBatchById(list);
        }
    }

    @Override
    public void flushIcon() {
        flushDataIcon();
    }

    @Override
    public Object history(CurrencyHistoryReq currencyHistoryReq ) {
        // https://api.currencybeacon.com/v1/timeseries?api_key=tjmXEnZkVTc6Bdrd8m02M76YEk76keen&base=HKD&end_date=2024-03-24&start_date=2023-08-23&symbols=CNY
        OkhttpResult<String> result = null;
        OkHttpParam param = new OkHttpParam();
        HashMap<String, Object> map = new HashMap<>();
        String api = "https://api.currencybeacon.com/v1/timeseries?api_key=" + appKey + "&base="
                + currencyHistoryReq.getFrom() + "&symbols="
                + currencyHistoryReq.getTo() + "&start_date="
                + currencyHistoryReq.getStartDate() + "&end_date="
                + currencyHistoryReq.getEndDate();
        param.setApiUrl(api);
        try {
            result = OkHttpClients.get(param, String.class);
            String apiRes = result.getResult();
            log.info("历史数据接口请求:{}", JSONObject.toJSONString(apiRes));
            JSONObject jsonObject = JSONObject.parseObject(apiRes);
            Object response = jsonObject.get("response");
            HashMap<String, Object> hashMap = JSONObject.parseObject(JSONObject.toJSONString(response), HashMap.class);
            hashMap.forEach((key, val) -> {
                HashMap<String, Object> mapVal = JSONObject.parseObject(JSONObject.toJSONString(val), HashMap.class);
                log.info("mapVal:{}",mapVal.toString());
                Object v = mapVal.get(currencyHistoryReq.getTo());
                map.put(key,v);
            });
        } catch (Exception e) {
            log.info("[失败]api:{},返回值:{}", api, result);
            e.printStackTrace();
        }
        // 排序
        LinkedHashMap<String, Object> collect = map.entrySet()
                .stream()
                .sorted(Map.Entry.comparingByKey())
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (oldValue, newValue) -> newValue, LinkedHashMap::new));
        return collect;
    }

    private void flushDataIcon(){
        //https://flagcdn.com/zh/codes.json
        String json = "{\n" +
                "    \"ad\": \"安道尔\",\n" +
                "    \"ae\": \"阿拉伯联合酋长国\",\n" +
                "    \"af\": \"阿富汗\",\n" +
                "    \"ag\": \"安提瓜和巴布达\",\n" +
                "    \"ai\": \"安圭拉\",\n" +
                "    \"al\": \"阿尔巴尼亚\",\n" +
                "    \"am\": \"亞美尼亞\",\n" +
                "    \"ao\": \"安哥拉\",\n" +
                "    \"aq\": \"南极洲\",\n" +
                "    \"ar\": \"阿根廷\",\n" +
                "    \"as\": \"美屬薩摩亞\",\n" +
                "    \"at\": \"奥地利\",\n" +
                "    \"au\": \"澳大利亚\",\n" +
                "    \"aw\": \"阿魯巴\",\n" +
                "    \"ax\": \"奥兰\",\n" +
                "    \"az\": \"阿塞拜疆\",\n" +
                "    \"ba\": \"波斯尼亚和黑塞哥维那\",\n" +
                "    \"bb\": \"巴巴多斯\",\n" +
                "    \"bd\": \"孟加拉国\",\n" +
                "    \"be\": \"比利时\",\n" +
                "    \"bf\": \"布吉納法索\",\n" +
                "    \"bg\": \"保加利亚\",\n" +
                "    \"bh\": \"巴林\",\n" +
                "    \"bi\": \"蒲隆地\",\n" +
                "    \"bj\": \"贝宁\",\n" +
                "    \"bl\": \"聖巴泰勒米\",\n" +
                "    \"bm\": \"百慕大\",\n" +
                "    \"bn\": \"汶莱\",\n" +
                "    \"bo\": \"玻利維亞\",\n" +
                "    \"bq\": \"荷蘭加勒比區\",\n" +
                "    \"br\": \"巴西\",\n" +
                "    \"bs\": \"巴哈马\",\n" +
                "    \"bt\": \"不丹\",\n" +
                "    \"bv\": \"布韦岛\",\n" +
                "    \"bw\": \"波札那\",\n" +
                "    \"by\": \"白俄罗斯\",\n" +
                "    \"bz\": \"伯利兹\",\n" +
                "    \"ca\": \"加拿大\",\n" +
                "    \"cc\": \"科科斯（基林）群島\",\n" +
                "    \"cd\": \"刚果民主共和国\",\n" +
                "    \"cf\": \"中非共和國\",\n" +
                "    \"cg\": \"刚果共和国\",\n" +
                "    \"ch\": \"瑞士\",\n" +
                "    \"ci\": \"科特迪瓦\",\n" +
                "    \"ck\": \"库克群岛\",\n" +
                "    \"cl\": \"智利\",\n" +
                "    \"cm\": \"喀麦隆\",\n" +
                "    \"cn\": \"中华人民共和国\",\n" +
                "    \"co\": \"哥伦比亚\",\n" +
                "    \"cr\": \"哥斯达黎加\",\n" +
                "    \"cu\": \"古巴\",\n" +
                "    \"cv\": \"佛得角\",\n" +
                "    \"cw\": \"库拉索\",\n" +
                "    \"cx\": \"圣诞岛\",\n" +
                "    \"cy\": \"賽普勒斯\",\n" +
                "    \"cz\": \"捷克\",\n" +
                "    \"de\": \"德国\",\n" +
                "    \"dj\": \"吉布提\",\n" +
                "    \"dk\": \"丹麦\",\n" +
                "    \"dm\": \"多米尼克\",\n" +
                "    \"do\": \"多明尼加\",\n" +
                "    \"dz\": \"阿尔及利亚\",\n" +
                "    \"ec\": \"厄瓜多尔\",\n" +
                "    \"ee\": \"爱沙尼亚\",\n" +
                "    \"eg\": \"埃及\",\n" +
                "    \"eh\": \"西撒哈拉\",\n" +
                "    \"er\": \"厄立特里亚\",\n" +
                "    \"es\": \"西班牙\",\n" +
                "    \"et\": \"埃塞俄比亚\",\n" +
                "    \"eu\": \"欧洲联盟\",\n" +
                "    \"fi\": \"芬兰\",\n" +
                "    \"fj\": \"斐濟\",\n" +
                "    \"fk\": \"福克兰群岛\",\n" +
                "    \"fm\": \"密克罗尼西亚联邦\",\n" +
                "    \"fo\": \"法罗群岛\",\n" +
                "    \"fr\": \"法国\",\n" +
                "    \"ga\": \"加蓬\",\n" +
                "    \"gb\": \"英国\",\n" +
                "    \"gb-eng\": \"英格兰\",\n" +
                "    \"gb-nir\": \"北爱尔兰\",\n" +
                "    \"gb-sct\": \"蘇格蘭\",\n" +
                "    \"gb-wls\": \"威爾斯\",\n" +
                "    \"gd\": \"格林纳达\",\n" +
                "    \"ge\": \"格鲁吉亚\",\n" +
                "    \"gf\": \"法屬圭亞那\",\n" +
                "    \"gg\": \"根西行政區\",\n" +
                "    \"gh\": \"加纳\",\n" +
                "    \"gi\": \"直布罗陀\",\n" +
                "    \"gl\": \"格陵兰\",\n" +
                "    \"gm\": \"冈比亚\",\n" +
                "    \"gn\": \"几内亚\",\n" +
                "    \"gp\": \"瓜德罗普\",\n" +
                "    \"gq\": \"赤道几内亚\",\n" +
                "    \"gr\": \"希腊\",\n" +
                "    \"gs\": \"南乔治亚和南桑威奇群岛\",\n" +
                "    \"gt\": \"危地马拉\",\n" +
                "    \"gu\": \"關島\",\n" +
                "    \"gw\": \"幾內亞比索\",\n" +
                "    \"gy\": \"圭亚那\",\n" +
                "    \"hk\": \"香港\",\n" +
                "    \"hm\": \"赫德島和麥克唐納群島\",\n" +
                "    \"hn\": \"洪都拉斯\",\n" +
                "    \"hr\": \"克罗地亚\",\n" +
                "    \"ht\": \"海地\",\n" +
                "    \"hu\": \"匈牙利\",\n" +
                "    \"id\": \"印度尼西亚\",\n" +
                "    \"ie\": \"爱尔兰\",\n" +
                "    \"il\": \"以色列\",\n" +
                "    \"im\": \"曼島\",\n" +
                "    \"in\": \"印度\",\n" +
                "    \"io\": \"英屬印度洋領地\",\n" +
                "    \"iq\": \"伊拉克\",\n" +
                "    \"ir\": \"伊朗\",\n" +
                "    \"is\": \"冰岛\",\n" +
                "    \"it\": \"意大利\",\n" +
                "    \"je\": \"澤西\",\n" +
                "    \"jm\": \"牙买加\",\n" +
                "    \"jo\": \"约旦\",\n" +
                "    \"jp\": \"日本\",\n" +
                "    \"ke\": \"肯尼亚\",\n" +
                "    \"kg\": \"吉尔吉斯斯坦\",\n" +
                "    \"kh\": \"柬埔寨\",\n" +
                "    \"ki\": \"基里巴斯\",\n" +
                "    \"km\": \"葛摩\",\n" +
                "    \"kn\": \"聖克里斯多福及尼維斯\",\n" +
                "    \"kp\": \"朝鲜民主主义人民共和国\",\n" +
                "    \"kr\": \"大韩民国\",\n" +
                "    \"kw\": \"科威特\",\n" +
                "    \"ky\": \"開曼群島\",\n" +
                "    \"kz\": \"哈萨克斯坦\",\n" +
                "    \"la\": \"老挝\",\n" +
                "    \"lb\": \"黎巴嫩\",\n" +
                "    \"lc\": \"圣卢西亚\",\n" +
                "    \"li\": \"列支敦斯登\",\n" +
                "    \"lk\": \"斯里蘭卡\",\n" +
                "    \"lr\": \"利比里亚\",\n" +
                "    \"ls\": \"莱索托\",\n" +
                "    \"lt\": \"立陶宛\",\n" +
                "    \"lu\": \"卢森堡\",\n" +
                "    \"lv\": \"拉脫維亞\",\n" +
                "    \"ly\": \"利比亚\",\n" +
                "    \"ma\": \"摩洛哥\",\n" +
                "    \"mc\": \"摩纳哥\",\n" +
                "    \"md\": \"摩尔多瓦\",\n" +
                "    \"me\": \"蒙特內哥羅\",\n" +
                "    \"mf\": \"法屬聖馬丁\",\n" +
                "    \"mg\": \"马达加斯加\",\n" +
                "    \"mh\": \"馬紹爾群島\",\n" +
                "    \"mk\": \"北馬其頓\",\n" +
                "    \"ml\": \"马里\",\n" +
                "    \"mm\": \"缅甸\",\n" +
                "    \"mn\": \"蒙古国\",\n" +
                "    \"mo\": \"澳門\",\n" +
                "    \"mp\": \"北马里亚纳群岛\",\n" +
                "    \"mq\": \"馬提尼克\",\n" +
                "    \"mr\": \"毛里塔尼亚\",\n" +
                "    \"ms\": \"蒙特塞拉特\",\n" +
                "    \"mt\": \"马耳他\",\n" +
                "    \"mu\": \"毛里求斯\",\n" +
                "    \"mv\": \"马尔代夫\",\n" +
                "    \"mw\": \"马拉维\",\n" +
                "    \"mx\": \"墨西哥\",\n" +
                "    \"my\": \"马来西亚\",\n" +
                "    \"mz\": \"莫桑比克\",\n" +
                "    \"na\": \"纳米比亚\",\n" +
                "    \"nc\": \"新喀里多尼亞\",\n" +
                "    \"ne\": \"尼日尔\",\n" +
                "    \"nf\": \"诺福克岛\",\n" +
                "    \"ng\": \"奈及利亞\",\n" +
                "    \"ni\": \"尼加拉瓜\",\n" +
                "    \"nl\": \"荷兰王国\",\n" +
                "    \"no\": \"挪威\",\n" +
                "    \"np\": \"尼泊尔\",\n" +
                "    \"nr\": \"諾魯\",\n" +
                "    \"nu\": \"紐埃\",\n" +
                "    \"nz\": \"新西兰\",\n" +
                "    \"om\": \"阿曼\",\n" +
                "    \"pa\": \"巴拿马\",\n" +
                "    \"pe\": \"秘鲁\",\n" +
                "    \"pf\": \"法屬玻里尼西亞\",\n" +
                "    \"pg\": \"巴布亚新几内亚\",\n" +
                "    \"ph\": \"菲律宾\",\n" +
                "    \"pk\": \"巴基斯坦\",\n" +
                "    \"pl\": \"波兰\",\n" +
                "    \"pm\": \"圣皮埃尔和密克隆\",\n" +
                "    \"pn\": \"皮特凯恩群岛\",\n" +
                "    \"pr\": \"波多黎各\",\n" +
                "    \"ps\": \"巴勒斯坦國\",\n" +
                "    \"pt\": \"葡萄牙\",\n" +
                "    \"pw\": \"帛琉\",\n" +
                "    \"py\": \"巴拉圭\",\n" +
                "    \"qa\": \"卡塔尔\",\n" +
                "    \"re\": \"留尼汪\",\n" +
                "    \"ro\": \"羅馬尼亞\",\n" +
                "    \"rs\": \"塞尔维亚\",\n" +
                "    \"ru\": \"俄罗斯\",\n" +
                "    \"rw\": \"卢旺达\",\n" +
                "    \"sa\": \"沙特阿拉伯\",\n" +
                "    \"sb\": \"所罗门群岛\",\n" +
                "    \"sc\": \"塞舌尔\",\n" +
                "    \"sd\": \"苏丹\",\n" +
                "    \"se\": \"瑞典\",\n" +
                "    \"sg\": \"新加坡\",\n" +
                "    \"sh\": \"圣赫勒拿、阿森松和特里斯坦-达库尼亚\",\n" +
                "    \"si\": \"斯洛文尼亚\",\n" +
                "    \"sj\": \"斯瓦巴和扬马延\",\n" +
                "    \"sk\": \"斯洛伐克\",\n" +
                "    \"sl\": \"塞拉利昂\",\n" +
                "    \"sm\": \"圣马力诺\",\n" +
                "    \"sn\": \"塞内加尔\",\n" +
                "    \"so\": \"索马里\",\n" +
                "    \"sr\": \"蘇利南\",\n" +
                "    \"ss\": \"南蘇丹\",\n" +
                "    \"st\": \"圣多美和普林西比\",\n" +
                "    \"sv\": \"萨尔瓦多\",\n" +
                "    \"sx\": \"荷屬聖馬丁\",\n" +
                "    \"sy\": \"叙利亚\",\n" +
                "    \"sz\": \"史瓦帝尼\",\n" +
                "    \"tc\": \"特克斯和凯科斯群岛\",\n" +
                "    \"td\": \"乍得\",\n" +
                "    \"tf\": \"法属南部和南极领地\",\n" +
                "    \"tg\": \"多哥\",\n" +
                "    \"th\": \"泰国\",\n" +
                "    \"tj\": \"塔吉克斯坦\",\n" +
                "    \"tk\": \"托克劳\",\n" +
                "    \"tl\": \"东帝汶\",\n" +
                "    \"tm\": \"土库曼斯坦\",\n" +
                "    \"tn\": \"突尼西亞\",\n" +
                "    \"to\": \"東加\",\n" +
                "    \"tr\": \"土耳其\",\n" +
                "    \"tt\": \"千里達及托巴哥\",\n" +
                "    \"tv\": \"圖瓦盧\",\n" +
                "    \"tw\": \"中華民國\",\n" +
                "    \"tz\": \"坦桑尼亚\",\n" +
                "    \"ua\": \"乌克兰\",\n" +
                "    \"ug\": \"乌干达\",\n" +
                "    \"um\": \"美国本土外小岛屿\",\n" +
                "    \"un\": \"联合国\",\n" +
                "    \"us\": \"美国\",\n" +
                "    \"uy\": \"乌拉圭\",\n" +
                "    \"uz\": \"乌兹别克斯坦\",\n" +
                "    \"va\": \"梵蒂冈\",\n" +
                "    \"vc\": \"圣文森特和格林纳丁斯\",\n" +
                "    \"ve\": \"委內瑞拉\",\n" +
                "    \"vg\": \"英屬維爾京群島\",\n" +
                "    \"vi\": \"美屬維爾京群島\",\n" +
                "    \"vn\": \"越南\",\n" +
                "    \"vu\": \"瓦努阿图\",\n" +
                "    \"wf\": \"瓦利斯和富圖納\",\n" +
                "    \"ws\": \"萨摩亚\",\n" +
                "    \"xk\": \"科索沃\",\n" +
                "    \"ye\": \"也门\",\n" +
                "    \"yt\": \"马约特\",\n" +
                "    \"za\": \"南非\",\n" +
                "    \"zm\": \"赞比亚\",\n" +
                "    \"zw\": \"辛巴威\"\n" +
                "}";

        log.info("解析数据:{}", JSONObject.toJSONString(json));
        //JSON字符串转换成JSON对象
        HashMap<String, String> hashMap = JSONObject.parseObject(json, HashMap.class);
        List<CurrencyMsgEntity> currencyMsgEntities = baseMapper.selectList(new QueryWrapper<CurrencyMsgEntity>().eq("is_often_used",1));
        currencyMsgEntities.forEach(obj -> {
            String substring = obj.getCurrencyEn().substring(0, 2).toLowerCase();
            String string = hashMap.get(substring);
            if (StrUtil.isNotEmpty(string)) {
                log.info("en:{},value:{}", obj.getCurrencyEn(), string);
                String url = "https://flagcdn.com/16x12/" + substring + ".png";
                obj.setCountryLetter(substring);
                obj.setIsOftenUsed(Constant.ONE);
                obj.setCountryZn(string);
                obj.setCurrencyIcon(url);
                baseMapper.updateById(obj);
            }
        });
    }

    /**
     * 获取BigDecimal
     *
     * @param value
     * @return
     */
    private BigDecimal getBigDecimal(Object value) {
        BigDecimal ret = null;
        if (value != null) {
            if (value instanceof BigDecimal) {
                ret = (BigDecimal) value;
            } else if (value instanceof String) {
                ret = new BigDecimal((String) value);
            } else if (value instanceof BigInteger) {
                ret = new BigDecimal((BigInteger) value);
            } else if (value instanceof Number) {
                ret = new BigDecimal(((Number) value).doubleValue());
            } else {
                throw new ClassCastException("Not possible to coerce [" + value + "] from class " + value.getClass() + " into a BigDecimal.");
            }
        }
        return ret;
    }
}
